#include "config_factory.h"
#include "cJSON.h"
#include "config_storage.h"
#include "factory_api.h"
#include "json_to_data.h"
#include <fal.h>
#include <rtdevice.h>
#include <rtthread.h>
#include <string.h>
#include <unistd.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME "fac_cfg"
#include "uc_log.h"

int add_test_cfg(cJSON *data_json, factory_test_t *config)
{
    cJSON *base_cfg_obj = cJSON_CreateObject();
    if (!base_cfg_obj)
    {
        return 1;
    }

    cJSON_AddStringToObject(base_cfg_obj, REMARK_NODE_CFG, config->remark);

    cJSON_AddNumberToObject(base_cfg_obj, STATE_NODE_CFG, config->state);

    cJSON_AddItemToObject(data_json, config->name, base_cfg_obj);

    return 0;
}
#if 0
static int add_factory_cfg(cJSON *data_json, factory_test_t *config)
{
    cJSON *gw_cfg_obj = cJSON_CreateObject();

    if (!gw_cfg_obj)
    {
        return 1;
    }

    add_test_cfg(gw_cfg_obj, config);

    cJSON_AddItemToObject(data_json, FACTORY_NODE, gw_cfg_obj);

    return 0;
}
#endif
int uc_write_factory_data(factory_test_t *config, int num)
{
    char *root = NULL, *data = NULL;
    unsigned int root_len = 0, data_len = 0, res = 0;
    unsigned char data_crc32 = 0;
    cJSON *root_json = cJSON_CreateObject();
    cJSON *data_json = cJSON_CreateObject();
    if (!root_json || !data_json)
    {
        goto end;
    }

    for (int n = 0; n < num; n++)
    {
        if (add_test_cfg(data_json, &config[n]))
        {
            cJSON_Delete(data_json);
            res = 1;
            goto end;
        }
    }

    /* 将data_json按照协议要求处理, 前面加上data_crc32, data_len */
    data = cJSON_Print(data_json);
	if (RT_NULL == data)
	{
		res = 2;
        goto end;
	}
    data_len = rt_strlen(data);
    for (int i = 0; i < data_len; i++)
    {
        data_crc32 += data[i];
    }
    rt_free(data);
    cJSON_AddNumberToObject(root_json, JSON_FACTORY_CRC32, data_crc32);
    cJSON_AddNumberToObject(root_json, JSON_FACTORY_LEN, data_len);
    cJSON_AddItemToObject(root_json, JSON_FACTORY_DATA, data_json);

    /* 将root_json转换为字符串，写入flash */
    root = cJSON_Print(root_json);
	if (RT_NULL == root)
	{
		res = 3;
        goto end;
	}
    root_len = rt_strlen(root);
    // TRACE_I("write config_file len %u:\n%s", root_len, root);
    res = config_file_write(FACTORY_FILE_PATH, root, root_len);
    rt_free(root);

end:
    cJSON_Delete(root_json);

    return res;
}

static int parse_factory_cfg(const cJSON *data_json, factory_test_t *factory_cfg, char *key)
{
    const cJSON *factory_cfg_obj = cJSON_GetObjectItemCaseSensitive(data_json, key);
    if (!factory_cfg_obj)
    {
        return -1;
    }

    rt_memcpy(factory_cfg->name, key, sizeof(factory_cfg->name));
    parse_uint32(factory_cfg_obj, STATE_NODE_CFG, &factory_cfg->state);
    parse_string(factory_cfg_obj, REMARK_NODE_CFG, factory_cfg->remark, sizeof(factory_cfg->remark));

    return 0;
}

int uc_read_factory_data(factory_test_t *static_data, int num)
{
    char ret = -1;
    char *root = NULL, *data = NULL;
    unsigned int root_len = 0, data_len = 0;
    unsigned char data_crc32 = 0, data_crc32_tmp = 0;
    cJSON *root_json = NULL, *data_json = NULL;

    /* 从flash读取配置文件，并转换为字符串 */
    root_len = config_file_get_len(FACTORY_FILE_PATH);
    root = rt_malloc(root_len + 4);
    if (root)
    {
        rt_memset(root, 0, root_len + 4);
    }
    else
    {
        ret = RT_ENOMEM;
        TRACE_E("uc_read_factory_data malloc fail");
        goto end;
    }
    config_file_read(FACTORY_FILE_PATH, root, root_len);
    // TRACE_I("read config_file len %u:\n%s", root_len, root);

    /* 检验配置文件完整性 */
    root_json = cJSON_Parse(root);
    if (!root_json)
    {
        ret = RT_EIO;
        TRACE_E("get root_json fail");
        goto end;
    }

    parse_uint8(root_json, JSON_FACTORY_CRC32, &data_crc32);
    parse_uint32(root_json, JSON_FACTORY_LEN, &data_len);
    data_json = cJSON_GetObjectItemCaseSensitive(root_json, JSON_FACTORY_DATA);
    if (!data_json)
    {
        ret = RT_EIO;
        TRACE_E("get data_json fail");
        goto end;
    }

    data = cJSON_Print(data_json);
	if (RT_NULL == data )
	{
		ret = RT_EIO;
        TRACE_E("cJSON_Print fail");
        goto end;
	}
    if (data_len != rt_strlen(data))
    {
        ret = RT_EINVAL;
        TRACE_E("uc_read_factory_data error, data_len != rt_strlen(data)");
        goto end;
    }

    for (int i = 0; i < data_len; i++)
    {
        data_crc32_tmp += data[i];
    }
    if (data_crc32 != data_crc32_tmp)
    {
        ret = RT_EINVAL;
        TRACE_E("uc_read_factory_data error, data_crc32 != data_crc32_tmp");
        goto end;
    }

    for (int n = 0; n < num; n++)
    {
        parse_factory_cfg(data_json, &static_data[n], factory_get_key(n));
    }

    TRACE_I("uc_read_factory_data success");
    ret = 0;

end:
    rt_free(root);
    rt_free(data);
    cJSON_Delete(root_json);

    return ret;
}

void factory_cfg(void)
{
    char *root = NULL, *data = NULL;
    unsigned int root_len = 0, data_len = 0;
    unsigned char data_crc32 = 0, data_crc32_tmp = 0;
    cJSON *root_json = NULL, *data_json = NULL;

    /* 从flash读取配置文件，并转换为字符串 */
    root_len = config_file_get_len(FACTORY_FILE_PATH);
    root = rt_malloc(root_len + 4);
    if (root)
    {
        rt_memset(root, 0, root_len + 4);
    }
    else
    {
        TRACE_E("show_cfg malloc fail");
        return;
    }
    config_file_read(FACTORY_FILE_PATH, root, root_len);
    rt_kprintf("read factory_file len %u:", root_len);
    // 串口buffer为256字节，这里按照200个字节分段打印
    int k = 0;
    char str_end;
    for (; k < root_len / 200; k++)
    {
        // 将root[200 * k + 200]写为\0用以保证只打印200个字节，打印完再还原
        str_end = root[200 * k + 200];
        root[200 * k + 200] = '\0';
        rt_kprintf("%s", &root[200 * k]);
        root[200 * k + 200] = str_end;
    }
    rt_kprintf("%s", &root[200 * k]);

    /* 检验配置文件完整性 */
    root_json = cJSON_Parse(root);
    if (!root_json)
    {
        TRACE_E("get root_json fail");
        goto end;
    }
    parse_uint8(root_json, JSON_FACTORY_CRC32, &data_crc32);
    parse_uint32(root_json, JSON_FACTORY_LEN, &data_len);
    data_json = cJSON_GetObjectItemCaseSensitive(root_json, JSON_FACTORY_DATA);
    if (!data_json)
    {
        TRACE_E("get data_json fail");
        goto end;
    }

    data = cJSON_Print(data_json);
    if (data_len != rt_strlen(data))
    {
        TRACE_E("error, data_len != rt_strlen(data)");
        goto end;
    }

    for (int i = 0; i < data_len; i++)
    {
        data_crc32_tmp += data[i];
    }

    if (data_crc32 != data_crc32_tmp)
    {
        TRACE_E("error, data_crc32 != data_crc32_tmp");
    }

end:
    rt_free(root);
    rt_free(data);
    cJSON_Delete(root_json);

    return;
}
#ifdef FINSH_USING_MSH

MSH_CMD_EXPORT(factory_cfg, read the config file and show it);
#endif
